#include "iic_2.hpp"
#include "system.hpp"
#include "apm32f0xx_gpio.h"
#include "stdio.h"

static GPIO_T *port_iic = GPIOB;
static GPIO_PIN_T pin_scl = GPIO_PIN_10;
static GPIO_PIN_T pin_sda = GPIO_PIN_11;

void _IIC2::IIC_SCL_0(void){GPIO_ClearBit(port_iic,pin_scl);}
void _IIC2::IIC_SCL_1(void){GPIO_SetBit(port_iic,pin_scl);}
void _IIC2::IIC_SDA_0(void){GPIO_ClearBit(port_iic,pin_sda);}
void _IIC2::IIC_SDA_1(void){GPIO_SetBit(port_iic,pin_sda);}
unsigned char _IIC2::READ_SDA(void){return GPIO_ReadInputBit(port_iic,pin_sda);}

void _IIC2::iic_delay(void){
	// int n;
    // for ( n = 0; n < 5000; n++ ){__asm__("nop");}
	//System_delayUs(1);
}

bool _IIC2::iicInit(void){
    GPIO_Config_T gpio_configuration;
    System_setPeripheralClockEnable(CLK_GPIOB,TRUE);
    gpio_configuration.pin = pin_scl | pin_sda;
    gpio_configuration.mode = GPIO_MODE_OUT;
    gpio_configuration.outtype = GPIO_OUT_TYPE_OD;
    gpio_configuration.speed = GPIO_SPEED_50MHz;
	gpio_configuration.pupd = GPIO_PUPD_PU;
    GPIO_Config(port_iic,&gpio_configuration);  
	return true;  
}


void _IIC2::iicStart(void){
	IIC_SDA_1();	 	  

	IIC_SCL_1();

	IIC_SDA_0();

	// iic_delay();
	// IIC_SCL_0();


	// IIC_SDA_1();	 	  
	// iic_delay();
	// IIC_SCL_1();
	// iic_delay();
	// IIC_SDA_0();

	// iic_delay();
	// IIC_SCL_0();
}

void _IIC2::iicStop(void){
	IIC_SCL_0();
	iic_delay();
	IIC_SDA_0();
	iic_delay();
	IIC_SCL_1(); 
	iic_delay();
	IIC_SDA_1();
	iic_delay();
}

unsigned char _IIC2::iicSendByte(unsigned char data){

    uint8_t iCount;
	IIC_SCL_0();
    for(iCount = 0;iCount < 8;iCount++){  
        	
		if((data & 0x80) >> 7) IIC_SDA_1();
		else IIC_SDA_0();	
		iic_delay();        
        IIC_SCL_1();
		iic_delay();
		IIC_SCL_0();
		data <<= 1;
    } 
		
    return 0;


    // uint8_t iCount;
    // for(iCount = 0;iCount < 8;iCount++){  
    //     IIC_SCL_0();
	// 	iic_delay();		
	// 	if((data & 0x80) >> 7) IIC_SDA_1();
	// 	else IIC_SDA_0();	
	// 	iic_delay();        
    //     IIC_SCL_1();
	// 	iic_delay();
	// 	data <<= 1;
    // } 
	// 	IIC_SCL_0();
    // return 0;
}

unsigned char _IIC2::iicReadByte(void){
	int i;
	unsigned char tmp=0;
	for(i=0;i<8;i++){
		tmp <<=1;
		tmp	|=READ_SDA();
		IIC_SCL_1();
		iic_delay();
		IIC_SCL_0();
	}
	return tmp;
}

unsigned char _IIC2::iicWaitack(void){

    uint8_t AckFlag;
    uint8_t uiVal = 0;    
	IIC_SDA_1();
	iic_delay();  
	IIC_SCL_1();
	iic_delay();
    AckFlag = 1;
	while(uiVal < 255){
        if(READ_SDA()==0){
		    AckFlag = 0;
		    break;
	    }uiVal++;
    }
	IIC_SCL_0();  
	return AckFlag;	


    // uint8_t AckFlag;
    // uint8_t uiVal = 0;  
	// IIC_SCL_0();
	// iic_delay();    
	// IIC_SDA_1();
	// IIC_SCL_1();
	// iic_delay();
    // AckFlag = 1;
	// while(uiVal < 255){
    //     if(READ_SDA()==0){
	// 	    AckFlag = 0;
	// 	    break;
	//     }uiVal++;
    // }
	// IIC_SCL_0();  
	// return AckFlag;	
}

void _IIC2::iicNack(void){
    IIC_SDA_1();	
	iic_delay();
	IIC_SCL_1();	
	iic_delay();
	IIC_SCL_0();
	iic_delay();
}

void _IIC2::iicAck(void){
	IIC_SDA_0();
	IIC_SCL_1();
	iic_delay();
	IIC_SCL_0();
	IIC_SDA_1();
}

static IIC2 *iic2 = nullptr;
IIC2 *IIC2::getInstance(){
    if( iic2 == nullptr ){
        iic2 = new _IIC2();
        iic2->iicInit();
    }
    return iic2;
}